/*
 * Copyright (c) 2012 free soft workgroup
 * All rights reserved
 *
 */
#include "http.h"

/*
 * static defines
 */
static const char *Request_Method[] = {"GET","POST","HEAD","DESCRIBE","OPTIONS","SETUP","PLAY","TEARDOWN","RECORD","ANNOUNCE","UNKNOW"};
static const char *Default_File_Format[]={".html",    ".htm",     ".flv",       ".fhv",       ".mp4",     ".mp3",       ".avi",           ".asf",          ".ogg",      ".ts",      ".ffm",                      ".rtp",".sdp",           ".m3u8",                ".ts",       ".htb",     ".info",    ".xml",    ".hb",      ".sb",      ".aspx",    ".none"};
static const char *Default_Mime_Types[] ={"text/html","text/html","video/x-flv","video/x-flv","video/mp4","audio/x-mp3","video/x-msvideo","video/x-ms-asf","video/ogg","video/MP2T","application/x-octet-stream","rtp", "application/sdp","application/x-mpegURL","video/mpeg","text/html","text/html","text/xml","text/html","text/html","text/html","application/x-octet-stream"};

static const char *CrossDomainXml = "<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\"/></cross-domain-policy>";
static const char* HTTP_VER0 = "HTTP/1.0";
static const char* HTTP_VER1 = "HTTP/1.1";
static const char* CRLF = "\r\n";
static const char* HTTP_RESPONSE_END = "\r\n\r\n";
static const char* HTTP_CONTENT_LENGTH = "Content-Length: ";
static const char* HTTP_RESPONSE_LINE_STR = "HTTP/1.1 200 OK\r\n";
static const char* HTTP_RESPONSE_PARTIAL_LINE_STR = "HTTP/1.1 206 Partial Content\r\n";
static const char* HTTP_RESPONSE_INVALID_LINE_STR = "HTTP/1.1 400 Request Invalid\r\n";
static const char* HTTP_ACCEPT_RANGES = "Accept-Ranges: bytes\r\n";


/*
 *
 * http handle class factory
 * */

http::http(void)
{

}

http::~http(void)
{

}

void http::init_request_header(http_request_header *request_header)
{
    if(request_header != NULL)
    {
        memset(request_header->path,'\0',MAX_REQ_PATH_LEN);
        memset(request_header->file_name, '\0', MAX_REQ_PATH_LEN);
        memset(request_header->pars, '\0', MAX_REQ_PATH_LEN);
        memset(request_header->privat, '\0', MAX_REQ_PATH_LEN);

        request_header->path_len = 0;
        request_header->file_name_len = 0;
        request_header->pars_len = 0;
        request_header->privat_len = 0;

        request_header->header_len = 0;
        request_header->content_length = 0;
        request_header->content_offset = 0;
        request_header->content_end = 0;

        request_header->method = UNKNOW;
        request_header->mime = NONE;
        request_header->httpstatus = CONNECTCLOSE;
        request_header->is_have_rang = false;

        request_header->id = 0;
        request_header->seek_time = 0;
        request_header->seek_offset = 0;
        request_header->opcode = 0;
        request_header->request_parse_result = 0;
    }
    return;
}


REQUEST_METHOD http::get_reqeust_method(char * buf,size_t size)
{
    int i = 0;
    for(;;)
    {
        if(SUCCESS == memcmp(buf,Request_Method[i],strlen(Request_Method[i])))
        {
            break;
        }

        if(UNKNOW == i)
           break;

        i++;
    }

    return (REQUEST_METHOD)i;
}

size_t http::get_line_len(char * buf,size_t size)
{
    size_t nindex = 0;
    char ch;
    bool bline = false;
    while(bline == false && nindex < size)
    {
        ch = (*(buf+nindex));
        switch( ch )
        {
                case '\r': // ignore
                        break;
                case '\n': // end-of-line
                        bline = true;
                        break;
                default:   // other....
                        break;
        }
        ++nindex;
    }

    /*check is find*/
    if(!bline)
         nindex = 0;

    return nindex;
}

int http::anlysis_path(http_request_header * request_header)
{
        if(request_header == NULL
                || request_header->path == NULL
                || request_header->path_len < 5)
                return FAILURE;
        /*begin parse url to uri struct*/
        int n_index = 0;
        int parse_result = 0;
        int n_size = (int)request_header->path_len;
        char * buf = request_header->path;
        char ch = 0;

        int nvar_start = 0;
        int nvar_len = 0;
        int nname_start = 0;
        int nname_len = 0;

        /*find url pars*/
        while(n_index < n_size)
        {
                ch = *(buf + n_index);
                switch(ch)
                {
                        case '?':
                                nname_start = n_index;
                                if((size_t)nname_start >= 5 && (size_t)nname_start < MAX_REQ_PATH_LEN)
                                {
                                        memcpy(request_header->file_name,buf,nname_start);
                                        request_header->file_name_len = nname_start;
                                        parse_result++;
                                }
                                nname_start = n_index + 1;
                                break;
                        case '=':
                                nvar_start = n_index + 1;
                                nname_len = n_index - nname_start;
                                break;
                        case '&':
                                /*
                                *offset
                                *start
                                *key
                                *videoname
                                *op
                                *pars
                                */
                                nvar_len = n_index - nvar_start;
                                if(nname_len == 2)
                                {
                                        if(0 == memcmp(buf + nname_start,"op",2) && nvar_len < 2 && nvar_len > 0)
                                        {
                                                char num_parse_array[3];
                                                memset(num_parse_array, '\0', 3);
                                                memcpy(num_parse_array,buf + nvar_start,nvar_len);
                                                request_header->opcode = atoi(num_parse_array);
                                                parse_result++;
                                        }
                                }
                                else if(nname_len == 3)
                                {
                                        if(0 == memcmp(buf + nname_start,"key",3)
                                                && nvar_len > 0
                                                && nvar_len <= 256
                                                && request_header->privat_len == 0)
                                        {
                                                memcpy(request_header->privat,"key:",4);
                                                memcpy(request_header->privat + 4,buf + nvar_start,nvar_len);
                                                request_header->privat_len = nvar_len + 4;
                                                parse_result++;
                                        }
                                }
                                else if(nname_len == 4)
                                {
                                        if(0 == memcmp(buf + nname_start,"pars",4) && (size_t)nvar_len < MAX_REQ_PATH_LEN)
                                        {
                                                memset(request_header->pars,'\0',MAX_REQ_PATH_LEN);
                                                memcpy(request_header->pars,buf + nvar_start,nvar_len);
                                                request_header->pars_len = nvar_len;
                                                parse_result++;
                                        }
                                }
                                else if(nname_len == 5)
                                {
                                        if(0 == memcmp(buf + nname_start,"ch_id",5)
                                                && nvar_len > 3
                                                && nvar_len < 5)
                                        {
                                                char num_parse_array[5];
                                                memset(num_parse_array, '\0',5);
                                                memcpy(num_parse_array,buf + nvar_start,nvar_len);
                                                request_header->id = atoi(num_parse_array);
                                                parse_result++;
                                        }
                                        else if(0 == memcmp(buf + nname_start,"start",5)
                                                && nvar_len > 0
                                                && nvar_len < 8)
                                        {
                                                char num_parse_array[8];
                                                memset(num_parse_array, '\0',8);
                                                memcpy(num_parse_array,buf + nvar_start,nvar_len);
                                                request_header->seek_time = atoi(num_parse_array);
                                                parse_result++;
                                        }
                                }
                                else if(nname_len == 6)
                                {
                                        if(0 == memcmp(buf + nname_start,"offset",6)
                                                && nvar_len > 0
                                                && nvar_len <= 12)
                                        {
                                                char num_parse_array[16];
                                                memset(num_parse_array, '\0',16);
                                                memcpy(num_parse_array,buf + nvar_start,nvar_len);
                                                request_header->seek_offset = strtoull(num_parse_array,NULL,10);
                                                parse_result++;
                                        }
                                }
                                else if(nname_len == 9)
                                {
                                        if(0 == memcmp(buf + nname_start,"videoname",9)
                                                && nvar_len > 0
                                                && (size_t)nvar_len < MAX_REQ_PATH_LEN)
                                        {
                                                memset(request_header->file_name,'\0',MAX_REQ_PATH_LEN);
                                                memcpy(request_header->file_name,buf + nvar_start,nvar_len);
                                                request_header->file_name_len = nvar_len;
                                                parse_result++;
                                        }
                                }
                                nname_start = n_index + 1;
                                break;
                        case '/':
                                if(request_header->file_name_len >0)
                                {
                                        buf[n_index] = '&';
                                        continue;
                                }
                                break;
                        default:
                                break;
                }
                n_index++;
        }
        /*no pars ,only get file name*/
        if(parse_result <= 0 && request_header->path_len < MAX_REQ_PATH_LEN + 1)
        {
            request_header->file_name_len = request_header->path_len - 1;
            memcpy(request_header->file_name,request_header->path,request_header->file_name_len);
        }
        /*parse end*/
        return SUCCESS;
        /*-end-*/
}

size_t http::get_url_pars_value(http_request_header * hrt,const char * name, char * buf, size_t buf_len)
{
    if(hrt == NULL || name == NULL || buf == NULL || buf_len == 0)
        return 0;

    if(hrt->path_len == 0)
        return 0;

    size_t ret = 0;
    size_t n_len = strlen(name);
    char * begin = NULL,* end = NULL;
    begin = strstr(hrt->path,name);
    if(begin != NULL)
    {
        end = strstr(begin,"&");
        if(end != NULL)
        {
             ret = end - begin - n_len;
        }
        else
        {
             ret = hrt->path_len - (begin - hrt->path) - n_len;
        }

        if(ret > 0 && ret < buf_len)
        {
             memcpy(buf,begin + n_len,ret);
        }
    }

    return ret;
}

HTTP_MIME http::anlysis_mime_type(http_request_header *request_header)
{
    if(request_header == NULL || request_header->file_name_len == 0)
        return NONE;

    char * pch = strrchr(request_header->file_name,'.');
    if(pch == NULL)
        return NONE;

    size_t  len = strlen(pch);
    if(len < 1 || len > 5)
        return NONE;
    /*check file ex name*/
    {
        int i = 0;
        for(;;)
        {
            if(SUCCESS == strcasecmp(pch,Default_File_Format[i]))
            {
                request_header->mime = (HTTP_MIME)i;
                break;
            }
            if(NONE == i)
                break;
            i++;
        }
    }

    return request_header->mime;
}

/*
* anlysis http_request_header::rang
*/
int http::anlysis_rang(http_request_header *request_header,char * rang,size_t len)
{
    if(request_header == NULL || rang == NULL || len == 0)
            return FAILURE;

    request_header->is_have_rang = true;
    /*Range: bytes=2344474-5898540*/
    /*Rang: bytes=1000-*/
    char * ch_begin = rang;
    char * ch_end = NULL;
    /*get rang min*/
    ch_end  = strstr(ch_begin,"-");
    if(ch_end != NULL)
    {
        size_t len = ch_end - ch_begin;
        if(len > 0 && len <= 12)
        {
            char num_parse_array[16];
            memset(num_parse_array,'\0',sizeof(num_parse_array));
            memcpy(num_parse_array,ch_begin ,len);
            request_header->content_offset = strtoull(num_parse_array,NULL,10);
            /*get rang max*/
            ch_begin = ch_end + 1;
            ch_end  = strstr(ch_begin,CRLF);
            if(ch_end !=NULL)
            {
                len = ch_end - ch_begin;
                if(len > 0 && len <= 12)
                {
                    memset(num_parse_array,'\0',sizeof(num_parse_array));
                    memcpy(num_parse_array,ch_begin ,len);
                    request_header->content_end = strtoull(num_parse_array,NULL,10);
                }
            }
        }
    }

    return SUCCESS;
}

int http::parse_request_header(http_request_header *request_header,char * buf,size_t size,int & errorcode)
{
	errorcode = 0;
    if(request_header == NULL || buf == NULL)
    {
    	errorcode = -1;
        return FAILURE;
    }

    if(size <= MIN_REQ_LEN || size >= MAX_REQ_LEN)
    {
    	errorcode = -2;
        return FAILURE;
    }

    /*init*/
    init_request_header(request_header);

    /*get request method*/
    request_header->method  = get_reqeust_method(buf,size);

    char * ptr = buf;
    size_t data_len = size;
    size_t line_len = 0;

    /*get first line*/
    line_len =  get_line_len(ptr,data_len);
    if(line_len < MIN_REQ_LEN || line_len >= size )
    {
    	 errorcode = 1;
         return FAILURE;
    }

    /*check request protocol*/
    if(SUCCESS != memcmp((ptr+line_len-10),HTTP_VER0,8)
            && SUCCESS != memcmp((ptr+line_len-10),HTTP_VER1,8))
    {
    	errorcode = 2;
        return FAILURE;
    }

    /*get request path*/
    if(line_len - 14 > MAX_REQ_PATH_LEN)
    {
    	errorcode = 3;
        return FAILURE;
    }

    size_t startindex = strlen(Request_Method[request_header->method]) + 1;
    if(line_len <= startindex + 11)
    {
    	errorcode = 4;
        return FAILURE;
    }

    request_header->path_len = line_len - startindex - 11;
    memcpy(request_header->path,ptr + startindex,request_header->path_len);

    /*get file name and pars*/
    strcat(request_header->path,"&");
    request_header->path_len ++;
    if(anlysis_path(request_header) != SUCCESS)
    {
    	errorcode = 5;
        return FAILURE;
    }
    else/*reset path*/
    {
        request_header->path[request_header->path_len-1] = '\0';
        request_header->path_len -- ;
    }

    /*get file type*/
    anlysis_mime_type(request_header);

    /*
    *get next line
    *get content length
    */
    ptr += line_len;
    char * ch_begin = NULL;
    char * ch_end = NULL;
    char num_parse_array[24];
    ch_begin = strstr(ptr,"Content-Length:");
    if(ch_begin != NULL)
    {
        ch_begin += 16;
        ch_end = strstr(ch_begin,CRLF);
        if(ch_end != NULL)
        {
            size_t len = ch_end - ch_begin;
            if(len < 24)
            {
                memset(num_parse_array, '\0', 24);
                memcpy(num_parse_array,ch_begin ,len);
                request_header->content_length = strtoull(num_parse_array,NULL,10);
            }
        }
    }
    /*get reqeust status  Connection:*/
    ch_begin = strstr(ptr,"Connection:");
    if(ch_begin != NULL)
    {
        ch_begin += 12;
        ch_end = strstr(ch_begin,CRLF);
        if(ch_end != NULL)
        {
            size_t len = ch_end - ch_begin;
            if(len == 10)
            {
                if(memcmp(ch_begin,"Keep-Alive",len) == 0 || memcmp(ch_begin,"keep-alive",len) == 0)
                {
                    request_header->httpstatus = KEEPALIVE;
                }
            }
        }
    }
    /*get reqeust private data*/
    size_t keylen = 11;
    ch_begin = strstr(ptr,"Mglivesvr:");
    if(ch_begin == NULL)
    {
        ch_begin = strstr(ptr,"Mgsvr:");
        keylen = 7;
    }
    /*check private data*/
    if(ch_begin != NULL)
    {
        ch_begin += keylen;
        ch_end = strstr(ch_begin,CRLF);
        if(ch_end != NULL)
        {
            size_t len = ch_end - ch_begin;
            if(len >0 && len < MAX_REQ_PATH_LEN)
            {
                memset(request_header->privat,'\0',MAX_REQ_PATH_LEN);
                memcpy(request_header->privat,ch_begin,len);
                request_header->privat_len = len;
            }
        }
    }
    /*get reqeust rang*/
    ch_begin = strstr(ptr,"Range: bytes=");
    if(ch_begin != NULL)
    {
        ch_begin += 13;
        ch_end = strstr(ch_begin,CRLF);
        if(ch_end != NULL)
        {
            size_t len = ch_end - ch_begin;
            if(len >0 && len < 64)
            {
                 anlysis_rang(request_header,ch_begin,len);
            }
        }
    }
    /*check completed request header*/
    ch_begin = strstr(buf,"\r\n\r\n");
    if(ch_begin != NULL)
    {
         request_header->header_len  = (ch_begin - buf + 4);
    }

    /*parse end*/
    return SUCCESS;
}

/*
*parse response length
*/
size_t http::parse_response_header(char * buf,int size,int &httpcode,uint64_t &Contentlength)
{
    httpcode = 0;
    Contentlength = 0;

    if(_NULL == buf || size <= 12)
        return 0;

    char chret[4];
    memcpy(chret,buf + 9,3);
    chret[3]='\0';
    httpcode = atoi(chret);
    /*get Content-Length:*/
    char * begin_index = _NULL;
    char * end_index = _NULL;
    size_t  ilen = 0;
    begin_index =  strstr(buf,"Content-Length: ");
    if(begin_index != _NULL)
    {
        begin_index += strlen("Content-Length: ");
        end_index = strstr(begin_index,CRLF);
        if(end_index != _NULL
            &&  end_index >= begin_index + 1
            &&  end_index < begin_index + 32)
        {
            char tempbuf[24];
            memset(tempbuf,'\0',24);
            ilen = end_index-begin_index;
            if(ilen < 24 && ilen > 0)
            {
                memcpy(tempbuf,begin_index,ilen);
                Contentlength = strtoull(tempbuf,NULL,10);
            }
        }
    }

    /*
     * check Content-Range,if is 206  part content data
     * then get the file length
     */
    if(httpcode == 206)
    {
        begin_index =  strstr(buf,"Content-Range: bytes ");
        if(begin_index != _NULL)
        {
            begin_index += strlen("Content-Range: bytes ");
            end_index = strstr(begin_index,CRLF);
            if(end_index != _NULL
               && end_index >= begin_index + 5
               && end_index < begin_index + 80)
            {
                 begin_index = strstr(begin_index,"/");
                 if(begin_index != NULL)
                 {
                     begin_index += 1;
                     if(end_index >= begin_index + 1 && end_index < begin_index + 24)
                     {
                         char tempbuf[24];
                         memset(tempbuf,'\0',24);
                         ilen = end_index - begin_index;
                         memcpy(tempbuf,begin_index,ilen);
                         Contentlength = strtoull(tempbuf,NULL,10);
                     }
                 }
            }
        }
    }

    /*check header length*/
    size_t header_len = 0;
    begin_index = strstr(buf,HTTP_RESPONSE_END);
    if(begin_index != _NULL)
    {
        begin_index += strlen(HTTP_RESPONSE_END);
        header_len = (size_t)(begin_index - buf);
    }
    /*end*/
    return header_len;
}

size_t http::struct_response_header(char * buf,HTTP_MIME mime_type,uint64_t content_len)
{
    if(_NULL == buf)
            return 0;
    char num_parse_array[32];

    strcpy(buf,HTTP_RESPONSE_LINE_STR);

    strcat(buf,"Content-Type: ");
    strcat(buf,Default_Mime_Types[mime_type]);
    strcat(buf,"\r\n");

    strcat(buf,HTTP_CONTENT_LENGTH);
    memset(num_parse_array,'\0',32);
    sprintf(num_parse_array,"%llu",content_len);
    strcat(buf,num_parse_array);
    strcat(buf,"\r\n");

    strcat(buf,HTTP_ACCEPT_RANGES);
    strcat(buf,"Connection: close\r\n");
    strcat(buf,"Server: xServer/Longwuwei-x-linux\r\n");
    strcat(buf,"\r\n");
    return strlen(buf);
}

/*
*struct response header
*/
size_t http::struct_response_header(char * buf,HTTP_MIME mime_type,uint64_t offset,uint64_t end,uint64_t content_length)
{
    if(_NULL == buf || end <= offset)
        return 0;

    if(end - offset + 1  > content_length)
        return 0;

    strcpy(buf,HTTP_RESPONSE_PARTIAL_LINE_STR);
    strcat(buf,"Content-Type: ");
    strcat(buf,Default_Mime_Types[mime_type]);
    strcat(buf,"\r\n");

    /*content-length*/
    sprintf(buf + strlen(buf),"%s%llu\r\n",HTTP_CONTENT_LENGTH,(end - offset + 1));

    /*
    *Content-Range: bytes offset-end/content_length\r\n
    */
    sprintf(buf + strlen(buf),"Content-Range: bytes %llu-%llu/%llu\r\n",offset,end,content_length);

    /*Connection*/
    strcat(buf,HTTP_ACCEPT_RANGES);
    strcat(buf,"Connection: close\r\n");
    strcat(buf,"Server: xServer/Longwuwei-x-linux\r\n");
    strcat(buf,"\r\n");

    return strlen(buf);
}

size_t http::struct_response_header(char * buf,HTTP_MIME mime_type,int code)
{
      if(_NULL == buf)
    	  return 0;
      if(code == 200)
      {
    	  strcpy(buf,HTTP_RESPONSE_LINE_STR);
      }
      else
      {
    	  strcpy(buf,HTTP_RESPONSE_INVALID_LINE_STR);
      }
      strcat(buf,"Content-Type: ");
      strcat(buf,Default_Mime_Types[mime_type]);
      strcat(buf,"\r\n");
      strcat(buf,HTTP_ACCEPT_RANGES);
      strcat(buf,"Server: xServer/Longwuwei-x-linux\r\n");
      strcat(buf,"Connection: close\r\n");
      strcat(buf,"Pragma: no-cache\r\n");
      strcat(buf,"Cache-Control: no-cache\r\n");
      strcat(buf,"\r\n");
      return strlen(buf);
}

size_t http::struct_response_header(char * buf,HTTP_MIME mime_type,const char * data)
{
      if(_NULL == buf || data == NULL)
              return 0;

      strcpy(buf,HTTP_RESPONSE_LINE_STR);
      strcat(buf,"Content-Type: ");
      strcat(buf,Default_Mime_Types[mime_type]);
      strcat(buf,"\r\n");
      strcat(buf,HTTP_ACCEPT_RANGES);
      strcat(buf,"Server: xServer/Longwuwei-x-linux\r\n");
      strcat(buf,"Connection: close\r\n");
      strcat(buf,"Pragma: no-cache\r\n");
      strcat(buf,"Cache-Control: no-cache\r\n");
      /*content-length*/
      sprintf(buf + strlen(buf)  , "%s%u\r\n" ,  HTTP_CONTENT_LENGTH , strlen(data));
      strcat(buf,"\r\n");

      strcat(buf,data);
      return strlen(buf);
}

/*
*struct response redirect header
*/
size_t http::struct_response_redirect_header(char * buf,const char * location)
{
	if(_NULL == buf || location == NULL)
	    return 0;

	 sprintf(buf,"HTTP/1.1 301 Moved Permanently\r\nLocation: %s\r\n",location);
	 strcat(buf,"Server: xServer/Longwuwei-x-linux\r\n");
	 strcat(buf,"Connection: close\r\n");
	 strcat(buf,"Pragma: no-cache\r\n");
	 strcat(buf,"Cache-Control: no-cache\r\n");
	 strcat(buf,"\r\n");

	 return strlen(buf);
}

size_t http::struct_crossxml_doma_response_header(char * buf)
{
      if(_NULL == buf)
          return 0;

      strcpy(buf,HTTP_RESPONSE_LINE_STR);
      strcat(buf,"Content-Type: ");
      strcat(buf,Default_Mime_Types[XML]);
      strcat(buf,"\r\n");
      strcat(buf,HTTP_ACCEPT_RANGES);
      strcat(buf,"Server: xServer/Longwuwei-x-linux\r\n");
      strcat(buf,"Connection: close\r\n");
      strcat(buf,"Pragma: no-cache\r\n");
      strcat(buf,"Cache-Control: no-cache\r\n");
      strcat(buf,"\r\n");
      strcat(buf,CrossDomainXml);

      return strlen(buf);
}

size_t http::struct_request_header(char * buf,size_t size,const char * path,const char * host,const char * privt,uint64_t offset,uint64_t end,uint64_t content_length)
{
    if(_NULL == buf)
        return 0;

    strcpy(buf,"GET /");
    strcat(buf,path);
    strcat(buf," HTTP/1.1\r\n");

    strcat(buf,"Accept: text/html, application/xhtml+xml, */*\r\n");

    if(privt != NULL)
    {
        strcat(buf,privt);
        strcat(buf,"\r\n");
    }

    strcat(buf,"User-Agent: xServer/Longwuwei-x-linux\r\n");

    if(host != NULL)
    {
        strcat(buf,"Host: ");
        strcat(buf,host);
        strcat(buf,"\r\n");
    }

    /*
     * Range: bytes=0-0
     * Range: bytes=0-
     */
    if(offset >= 0 && end > 0)
    {
        sprintf(buf + strlen(buf),"Range: bytes=%llu-%llu\r\n",offset,end);
    }
    else if(offset > 0)
    {
        sprintf(buf + strlen(buf),"Range: bytes=%llu-\r\n",offset);
    }

    /**
     * Content-Length:
     */
    if(content_length > 0)
    {
    	sprintf(buf + strlen(buf),"%s%llu\r\n",HTTP_CONTENT_LENGTH , content_length);
    }

    strcat(buf,"Connection: close\r\n");
    strcat(buf,"\r\n");
    return strlen(buf);
}
